using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Security;
namespace Net35.Xrm.Sdk
{
	internal sealed class AssemblyBasedKnownProxyTypesProvider : KnownProxyTypesProvider
	{
		private sealed class EarlyBoundTypeMap : Dictionary<string, Type>
		{
		}
		private sealed class EarlyBoundNameMap : Dictionary<Type, string>
		{
		}
		private static Dictionary<Assembly, AssemblyBasedKnownProxyTypesProvider.EarlyBoundTypeMap> _earlyBoundTypesMapByAssembly;
		private static Dictionary<Assembly, AssemblyBasedKnownProxyTypesProvider.EarlyBoundNameMap> _earlyBoundNamesMapByAssembly;
		private Assembly _currentlyLoadingAssembly;
		[SecuritySafeCritical]
		internal AssemblyBasedKnownProxyTypesProvider()
		{
			AssemblyBasedKnownProxyTypesProvider._earlyBoundTypesMapByAssembly = new Dictionary<Assembly, AssemblyBasedKnownProxyTypesProvider.EarlyBoundTypeMap>();
			AssemblyBasedKnownProxyTypesProvider._earlyBoundNamesMapByAssembly = new Dictionary<Assembly, AssemblyBasedKnownProxyTypesProvider.EarlyBoundNameMap>();
		}
		public override Type GetTypeForName(string name, Assembly proxyTypesAssembly)
		{
			if (proxyTypesAssembly == null)
			{
				return null;
			}
			base.RegisterAssembly(proxyTypesAssembly);
			lock (KnownProxyTypesProvider.ThisLock)
			{
				AssemblyBasedKnownProxyTypesProvider.EarlyBoundTypeMap earlyBoundTypeMap = null;
				if (AssemblyBasedKnownProxyTypesProvider._earlyBoundTypesMapByAssembly.TryGetValue(proxyTypesAssembly, out earlyBoundTypeMap) && earlyBoundTypeMap.ContainsKey(name))
				{
					return earlyBoundTypeMap[name];
				}
			}
			return null;
		}
		public override string GetNameForType(Type type)
		{
			Assembly assembly = type.Assembly;
			base.RegisterAssembly(assembly);
			lock (KnownProxyTypesProvider.ThisLock)
			{
				AssemblyBasedKnownProxyTypesProvider.EarlyBoundNameMap earlyBoundNameMap = null;
				if (AssemblyBasedKnownProxyTypesProvider._earlyBoundNamesMapByAssembly.TryGetValue(assembly, out earlyBoundNameMap) && earlyBoundNameMap.ContainsKey(type))
				{
					return earlyBoundNameMap[type];
				}
			}
			return null;
		}
		protected override void AddTypeMapping(Assembly assembly, Type type, string proxyName)
		{
			AssemblyBasedKnownProxyTypesProvider.EarlyBoundTypeMap earlyBoundTypeMap = null;
			AssemblyBasedKnownProxyTypesProvider._earlyBoundTypesMapByAssembly.TryGetValue(assembly, out earlyBoundTypeMap);
			if (earlyBoundTypeMap == null)
			{
				earlyBoundTypeMap = new AssemblyBasedKnownProxyTypesProvider.EarlyBoundTypeMap();
				AssemblyBasedKnownProxyTypesProvider._earlyBoundTypesMapByAssembly[assembly] = earlyBoundTypeMap;
			}
			if (earlyBoundTypeMap.ContainsKey(proxyName))
			{
				throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "A proxy type with the name {0} has been defined by multiple types. Current type: {1}, Existing type: {2}", new object[]
				{
					proxyName,
					type.AssemblyQualifiedName,
					earlyBoundTypeMap[proxyName].AssemblyQualifiedName
				}), proxyName);
			}
			earlyBoundTypeMap.Add(proxyName, type);
			AssemblyBasedKnownProxyTypesProvider.EarlyBoundNameMap earlyBoundNameMap = null;
			AssemblyBasedKnownProxyTypesProvider._earlyBoundNamesMapByAssembly.TryGetValue(assembly, out earlyBoundNameMap);
			if (earlyBoundNameMap == null)
			{
				earlyBoundNameMap = new AssemblyBasedKnownProxyTypesProvider.EarlyBoundNameMap();
				AssemblyBasedKnownProxyTypesProvider._earlyBoundNamesMapByAssembly[assembly] = earlyBoundNameMap;
			}
			if (earlyBoundNameMap.ContainsKey(type))
			{
				throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "A proxy type with the name {0} has been defined by multiple types. Current type: {1}, Existing type: {2}", new object[]
				{
					proxyName,
					type.AssemblyQualifiedName,
					type.AssemblyQualifiedName
				}), proxyName);
			}
			earlyBoundNameMap.Add(type, proxyName);
		}
		protected override void OnBeginLoadTypes(Assembly targetAssembly)
		{
			this._currentlyLoadingAssembly = targetAssembly;
		}
		protected override void OnEndLoadTypes()
		{
			this._currentlyLoadingAssembly = null;
		}
		protected override void OnErrorLoadTypes()
		{
			if (this._currentlyLoadingAssembly != null && AssemblyBasedKnownProxyTypesProvider._earlyBoundTypesMapByAssembly.ContainsKey(this._currentlyLoadingAssembly))
			{
				AssemblyBasedKnownProxyTypesProvider._earlyBoundTypesMapByAssembly.Remove(this._currentlyLoadingAssembly);
			}
			this._currentlyLoadingAssembly = null;
		}
	}
}
